﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using HandyControl.Controls;
using Koala.Pro.Common;
using Koala.Pro.Core;
using Koala.Pro.Models;
using Koala.Pro.Services;
using System.Reflection;

namespace Koala.Pro.ViewModels
{
    public abstract partial class BaseEditViewModel<TEntity, TKey, TGetListInput> : BaseViewModel where TEntity : class, IEntity<TKey>, new() where TGetListInput : IPagedAndSortedResultRequest, new()
    {
        [ObservableProperty]
        private TEntity item = new TEntity();

        [ObservableProperty]
        private bool isEdit;

        [ObservableProperty]
        private bool isReadOnly;

        protected IMyCrudService<TEntity, TKey, TGetListInput> service { get; set; }

        public BaseEditViewModel(IMyCrudService<TEntity, TKey, TGetListInput> service)
        {
            this.service = service;
        }

        public override void OnNavigatedTo()
        {
            if (!base.Title.IsNullOrEmpty())
            {
                base.Title = base.Title.Replace("编辑-", "").Replace("新增-", "");
                base.Title = (IsEdit ? ("编辑-" + base.Title) : ("新增-" + base.Title));
            }
            base.OnNavigatedTo();
        }

        [RelayCommand]
        public virtual async Task Save()
        {
            bool success = false;
            string text;
            try
            {
                success = await InsertOrUpdate();
                text = (success ? "操作成功" : "操作失败");
            }
            catch (Exception ex)
            {
                LogTextHelper.Error(ex);
                text = ex.Message;
            }
            if (success)
            {
                Growl.SuccessGlobal(text);
            }
            else
            {
                Growl.ErrorGlobal(text);
            }
            base.Result = new CommonResult(success, text);
        }

        protected virtual async Task<bool> InsertOrUpdate()
        {
            if (Item == null)
            {
                return false;
            }
            return await service.InsertOrUpdateAsync(Item, Item.Id);
        }

        public new void NotifyChanged(string propertyName = "Item")
        {
            OnPropertyChanged(propertyName);
        }

        public virtual void OnBeforeInsert(bool withOU = true)
        {
            if (Item != null)
            {
                SetProperty(Item, "Creator", App.ViewModel.UserInfo.Id);
                SetProperty(Item, "CreateTime", DateTime.Now);
                if (withOU)
                {
                    SetProperty(Item, "Company_ID", App.ViewModel.UserInfo.Company_ID);
                    SetProperty(Item, "Dept_ID", App.ViewModel.UserInfo.Dept_ID);
                    SetProperty(Item, "CompanyName", App.ViewModel.UserInfo.CompanyName);
                    SetProperty(Item, "DeptName", App.ViewModel.UserInfo.DeptName);
                }
            }
        }

        public virtual void OnBeforeUpdate(bool withOU = true)
        {
            if (Item != null)
            {
                SetProperty(Item, "Editor", App.ViewModel.UserInfo.Id);
                SetProperty(Item, "EditTime", DateTime.Now);
                if (withOU)
                {
                    SetProperty(Item, "Company_ID", App.ViewModel.UserInfo.Company_ID);
                    SetProperty(Item, "Dept_ID", App.ViewModel.UserInfo.Dept_ID);
                    SetProperty(Item, "CompanyName", App.ViewModel.UserInfo.CompanyName);
                    SetProperty(Item, "DeptName", App.ViewModel.UserInfo.DeptName);
                }
            }
        }

        private void SetProperty(TEntity obj, string name, object? value)
        {
            try
            {
                PropertyInfo property = obj.GetType().GetProperty(name);
                if (property != null && value != null)
                {
                    value = Convert.ChangeType(value, property.PropertyType);
                    property.SetValue(obj, value, null);
                }
            }
            catch
            {
            }
        }
    }
}
